<?php

declare(strict_types=1);

namespace Zlf\AppValidate\Rule;

/**
 * 坐标验证器
 */
class PointValidate extends RuleAbstract
{
    /**
     * 默认错误消息
     * @var string
     */
    protected $_error = '{label}不是有效的坐标';

    /**
     * 开始验证
     *
     * 验证输入值是否为有效的地理坐标（经度和纬度）。坐标必须是一个包含 'lng' 和 'lat' 键的数组，且对应的值需符合地理坐标的范围要求。
     *
     * @param mixed $value 需要验证的值
     * @param string $label 字段标签，用于错误提示信息中
     * @return bool 验证结果：成功为 true，失败为 false
     */
    public function validate($value, string $label = ''): bool
    {
        // 检查输入是否为数组
        if (!is_array($value)) {
            $this->addError($this->_error, $label);
            return false;
        }

        // 检查数组中是否包含 'lng' 和 'lat' 键，并获取其值
        if (isset($value['lng']) && isset($value['lat'])) {
            $lng = strval($value['lng']);
            $lat = strval($value['lat']);

            // 如果允许跳过空值并且值为空，则直接通过验证
            if (empty($value) && $this->_noSkipping === true) {
                $this->_value = $value;
                return true;
            }

            // 使用正则表达式检查经纬度的有效性
            if (preg_match('/^-?((\d|[1-9]\d|1[0-7]\d)(\.\d+)?|180(\.0+)?)$/', $lng) &&
                preg_match('/^-?((\d|[1-8]\d)(\.\d+)?|90(\.0+)?)$/', $lat)) {
                $this->_value = $value;
                return true;
            }
        }

        // 输入不符合条件时添加错误信息并返回 false
        $this->addError($this->_error, $label);
        return false;
    }
}